﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.IO;
using CCWin.SkinControl;
using GroupChat2013.Common;
using System.Drawing.Imaging;
using CCWin;
using GroupChat2013.Logic;
using System.Threading;
using System.Collections;
using GroupChat2013.Entity;
using GroupChat2013.Interface;
using GroupChat2013.Main.Properties;
using System.Drawing.Drawing2D;
using GroupChat2013.Service;

namespace GroupChat2013.Main.Controls
{
    public partial class ChatPanel : UserControl
    {
        #region 变量

        /// <summary>
        /// 表情框
        /// </summary>
        public FrmCountenance _faceForm;

        /// <summary>
        /// 表情窗体
        /// </summary>
        public FrmCountenance m_FaceForm
        {
            get
            {
                if (this._faceForm == null)
                {
                    this._faceForm = new FrmCountenance()
                    {

                        ImagePath = GroupChat2013.Common.Helper.CombinePath(@"Face\\"),
                        CustomImagePath = GroupChat2013.Common.Helper.CombinePath(@"Face\\Custom\\"),
                        CanManage = true,
                        ShowDemo = true,
                    };

                    this._faceForm.Init(24, 24, 8, 8, 12, 8);
                    this._faceForm.Selected += this._faceForm_AddFace;

                }

                return this._faceForm;
            }
        }

        /// <summary>
        /// 发送图片目录
        /// </summary>
        private string ImageBasePath
        {
            get
            {
                return EngineContext.Current.FilePathManager.ImagePath;
            }
        }

        private string TITLEFORMAT = "{0} ";

        /// <summary>
        /// 是否结束线程标志
        /// </summary>
        private bool m_HasItem = true;

        /// <summary>
        /// 需要接收的图片文件
        /// </summary>
        public Queue m_NeedRecPictures;

        /// <summary>
        /// 线程同步信号
        /// </summary>
        private AutoResetEvent m_AutoReset = new AutoResetEvent(false);

        /// <summary>
        /// 下载图片线程
        /// </summary>
        private Thread m_DownImgThread;

        /// <summary>
        /// 聊天信息操作
        /// </summary>
        public IMessage messageManage;

        /// <summary>
        /// 聊天配置
        /// </summary>
        private ChatConfigInfo configInfo;

        #endregion

        #region 自定义事件

        /// <summary>
        /// 发送事件代理
        /// </summary>
        /// <param name="Msg">要发送的消息</param>
        public delegate void CreateMsgEventHandler(object sender, MessageContent Msg);

        /// <summary>
        /// 登录密码错误事件
        /// </summary>
        public event CreateMsgEventHandler CreateMsgAfter;

        public delegate void SendFileEventHandler(object sender, List<string> fileNames);

        /// <summary>
        /// 发送文件
        /// </summary>
        public event SendFileEventHandler SendFile;

        /// <summary>
        /// 消息框按键事件
        /// </summary>
        public event KeyEventHandler SendKeyDownHandler;

        /// <summary>
        /// 点击聊天记录按钮
        /// </summary>
        public event Action ChatRecordClickedHandler;

        #endregion

        #region 构造函数

        public ChatPanel()
        {
            InitializeComponent();

            this.txtSend.KeyDown += new KeyEventHandler(txtSend_KeyDown);
            this.txtSend.DragDrop += new DragEventHandler(txtSend_DragDrop);
            this.txtSend.DragEnter += new DragEventHandler(txtSend_DragEnter);
            this.txtSend.AllowDrop = true;

            this.txtRecord.MouseDoubleClick += new MouseEventHandler(txtRecord_MouseDoubleClick);
            this.txtRecord.LinkClicked += new LinkClickedEventHandler(txtRecord_LinkClicked);

            this.toolFont.Click += new EventHandler(toolFont_Click);
            this.toolCountenance.Click += new EventHandler(toolCountenance_Click);
            this.toolImgFile.Click += new EventHandler(toolImgFile_Click);
            this.toolPrintScreen.Click += new EventHandler(toolPrintScreen_Click);
            this.tsbClearP.Click += new EventHandler(tsbClearP_Click);
            this.tsbChatRecord.Click += new EventHandler(tsbChatRecord_Click);

            this.Load += new EventHandler(ChatPanel_Load);
        }

        #endregion

        #region 窗体事件

        private void ChatPanel_Load(object sender, EventArgs e)
        {
            
        }

        private void txtRecord_LinkClicked(object sender, LinkClickedEventArgs e)
        {
            string url = GroupChat2013.Common.Helper.AddUrlParams(e.LinkText, "cid=" + EngineContext.Current.CurrUserInfo.CID);
            FrmGroup.OpenWithChrome(url);
        }

        #endregion

        #region 公共方法

        #region 清除消息文本
        
        /// <summary>
        /// 清除发送过的消息文本
        /// </summary>
        public void ClearSendMsgTextBox()
        {
            txtSend.Clear();
            txtSend.Focus();
            txtSend.Select(0, 0);
        }

        /// <summary>
        /// 清楚发送过的图片缓存
        /// </summary>
        public void ClearSendImageCache()
        {
            this.txtSend.RemoveAllGifControl();
        }

        #endregion
        
        #region 获得要发送的图片集合
        /// <summary>
        /// 获得要发送的图片集合
        /// </summary>
        /// <returns></returns>
        public List<MyPicture> GetSendPicture()
        {
            return txtSend.GetExistGifs();
        }
        #endregion

        #region 添加文本到对话记录文本框
        /// <summary>
        /// 添加文本到对话记录文本框
        /// </summary>
        /// <param name="text"></param>
        public void addRemarkTextToRecord(string text)
        {
            int iniPos = txtRecord.TextLength;//获得当前记录richBox中最后的位置
            Color titleColor = Color.Brown;
            txtRecord.AppendText(text);
            txtRecord.Select(iniPos, txtRecord.TextLength - iniPos);
            txtRecord.SelectionFont = new Font("宋体", 10);
            txtRecord.SelectionColor = titleColor;
            txtRecord.AppendText("\n");
            txtRecord.Select(txtRecord.TextLength, 0);
            txtRecord.ScrollToCaret();
        }
        #endregion

        #region 释放资源

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Release()
        {
            try { m_DownImgThread.Abort(); }
            catch { }

            this.txtRecord.RemoveAllGifControl();
            this.txtSend.RemoveAllGifControl();
            
            _faceForm = null;
            m_NeedRecPictures.Clear();
        }

        #endregion

        #region 设置字体、颜色

        public void SetFontStyle(ChatConfigInfo configInfo)
        {
            this.configInfo = configInfo;

            this.txtSend.ForeColor = configInfo.Color;
            this.txtSend.Font = configInfo.Font;
        }

        #endregion

        #region 返回默认的文字配置

        public static ChatConfigInfo GetDefault()
        {
            return new ChatConfigInfo()
            {
                FontBold = false,
                FontColor = 16777216,
                FontItalic = false,
                FontName = "宋体",
                FontSize = 9,
                FontStrikeout = false,
                FontUnderline = false,
                SendMode = 1
            };
        }

        #endregion

        #endregion

        #region 功能栏事件

        /// <summary>
        /// 显示字体对话框
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolFont_Click(object sender, EventArgs e)
        {
            FontDialog fd = new FontDialog();
            fd.ShowColor = true;
            fd.Font = this.txtSend.Font;
            fd.Color = this.txtSend.ForeColor;

            if (fd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.txtSend.Font = fd.Font;
                this.txtSend.ForeColor = fd.Color;

                if (configInfo != null)
                {
                    configInfo.Color = this.txtSend.ForeColor;
                    configInfo.Font = this.txtSend.Font;
                }
            }
        }

        #region 表情窗体与事件

        string imgName = "";
        void _faceForm_AddFace(object sender, SelectFaceArgs e)
        {
            this.imgName = e.Img.FullName.Replace(Application.StartupPath + "\\", "");
            imgName = GroupChat2013.Common.Helper.CombinePath(imgName);

            if (System.IO.File.Exists(imgName))
            {
                System.Drawing.Image image = System.Drawing.Image.FromFile(imgName);
                this.txtSend.addGifControl(e.Img.Name, e.Img.Image);
            }
        }

        /// <summary>
        /// 表情
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolCountenance_Click(object sender, EventArgs e)
        {
            Point pt = this.PointToScreen(new Point(skToolMenu.Left + 30 - this.m_FaceForm.Width / 2, (skToolMenu.Top - this.m_FaceForm.Height)));
            this.m_FaceForm.Show(pt.X, pt.Y, skToolMenu.Height);
        }

        #endregion

        #region  插入图片

        /// <summary>
        /// 插入图片
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolImgFile_Click(object sender, EventArgs e)
        {
            DialogResult result = openPictureDialog.ShowDialog();
            if (result == DialogResult.OK)
            {
                string path = openPictureDialog.FileName;

                if (!File.Exists(path))
                {
                    MessageBoxEx.Show("未检测到有效的图片路径", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                if (path.IndexOf("+") > 0)
                {
                    MessageBoxEx.Show("检测到图片路径中存在无法识别的特殊字符", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                FileInfo fi = new FileInfo(path);
                if (fi.Length / 1024 > ConstClass.MaxInsertImageSize)
                {
                    MessageBoxEx.Show("聊天内容内嵌图片最大支持图片大小为" + ConstClass.MaxInsertImageSize + "KB，过大的图片可以使用文件上传方式上传。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                Image image = Image.FromFile(path);
                SaveAddImage(image);
            }
        }

        #endregion

        #region 屏幕截图

        //截图方法
        private FrmCapture m_frmCapture;
        /// <summary>
        /// 截图
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolPrintScreen_Click(object sender, EventArgs e)
        {
            if (m_frmCapture == null || m_frmCapture.IsDisposed)
            {
                m_frmCapture = new FrmCapture();
                m_frmCapture.CaptureCompletedHandler += (img) =>
                {
                    Image image = (Bitmap)img.Clone();
                    if (image != null)
                    {
                        Clipboard.SetImage(image);

                        SaveAddImage(image);
                    }
                };
                m_frmCapture.IsCaptureCursor = false;
                m_frmCapture.Show();
            }
        }

        private void tsbClearP_Click(object sender, EventArgs e)
        {
            txtRecord.Clear();
            txtRecord.Focus();
            txtRecord.Select(0, 0);

            txtSend.Focus();
        }

        #endregion

        /// <summary>
        /// 群聊天信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void tsbChatRecord_Click(object sender, EventArgs e)
        {
            //this.txtRecord.Clear();
            //this.txtSend.Focus();
            //this.txtSend.Select(txtSend.TextLength, 0);
            //this.Invalidate();

            if (ChatRecordClickedHandler != null)
                ChatRecordClickedHandler();
        }

        /// <summary>
        /// 保存图片并添加到发送Richtextbox
        /// </summary>
        /// <param name="image"></param>
        private void SaveAddImage(Image image)
        {
            Tools.CreateDir(ImageBasePath);
            string fileName = ImageBasePath + "\\temp.gif";
            image.Save(fileName);
            string md5 = Hasher.GetMD5Hash(fileName);
            string Md5fileName = ImageBasePath + "\\" + md5 + ".gif";

            if (!System.IO.File.Exists(Md5fileName))
            {
                System.IO.File.Delete(fileName);

                System.Drawing.Imaging.Encoder MyEncoder = System.Drawing.Imaging.Encoder.Quality;
                EncoderParameters encoderParas = new EncoderParameters(1);
                EncoderParameter encoderPara = new EncoderParameter(MyEncoder, 0);
                encoderParas.Param[0] = encoderPara;
                ImageCodecInfo codecInfo = ImageCodecInfo.GetImageEncoders()[0];
                image.Save(Md5fileName, codecInfo, encoderParas);
            }
            this.txtSend.addGifControl(md5, image);
        }

        #endregion

        #region 发送消息
        /// <summary>
        /// Sends currently typed text from active wrie tab.
        /// </summary>
        public void SendMsg()
        {
            try
            {
                string text = "";
                text = this.txtSend.Text;

                if (text.Length == 0)
                    return;

                MessageContent msg = GetSendMsg();
                if (CreateMsgAfter != null)
                    CreateMsgAfter(this, msg);//触发发送消息事件

            }
            catch (Exception x)
            {
                MessageBox.Show(this, "Error: " + x.ToString(), "Error:", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion

        #region 将用户对话消息插入消息记录区

        public void WriteNoticeToRichTextBox(string message)
        {
            int iniPos = txtRecord.TextLength;//获得当前记录richBox中最后的位置
            Color titleColor = Color.Gray;

            txtRecord.AppendText(" " + message);
            txtRecord.Select(iniPos, txtRecord.TextLength - iniPos);
            txtRecord.SelectionFont = new Font("宋体", 9);
            txtRecord.SelectionColor = titleColor;
            txtRecord.AppendText("\n");
        }

        /// <summary>
        /// 讲接收到的消息写入消息记录区
        /// </summary>
        /// <param name="msg"></param>
        public void ReceiveToRichTextBox(MessageContent msg)
        {
            MsgToRichTextBox(msg, false, true);
        }

        /// <summary>
        /// 将自己发送的消息加入 RichTextBox 控件
        /// </summary>
        /// <param name="msg">消息类</param>
        /// <param name="IsSend">标记是发送消息还是收到消息</param>
        /// <param name="title">标记如果是发送状态下 是否发送成功</param>
        public void SendToRichTextBox(MessageContent msg, bool isSendSucc)
        {
            MsgToRichTextBox(msg, true, isSendSucc);
        }

        /// <summary>
        /// 将用户对话消息加入 RichTextBox 控件
        /// </summary>
        /// <param name="msg">消息类</param>
        /// <param name="IsSend">标记是发送消息还是收到消息</param>
        /// <param name="title">标题（用户名+用户ID）</param>
        private void MsgToRichTextBox(MessageContent msg, bool IsSend, bool isSendSucc)
        {
            if (msg == null) return;

            string title = string.Format(TITLEFORMAT, msg.FromName);
            int iniPos = txtRecord.TextLength;//获得当前记录richBox中最后的位置
            title += DateTime.Now.ToLongTimeString();
            Color titleColor = Color.Green;

            if (!IsSend)//如果是收到消息
                titleColor = Color.Blue;

            txtRecord.AppendText(" " + title);
            txtRecord.Select(iniPos, txtRecord.TextLength - iniPos);
            txtRecord.SelectionFont = new Font("宋体", 10);
            txtRecord.SelectionColor = titleColor;

            //txtRecord.AppendText("\n  ");

            iniPos = txtRecord.TextLength;//获得当前记录richBox中最后的位置

            //如果消息中有图片，则添加图片
            if (!string.IsNullOrEmpty(msg.ImageInfo))
            {
                string[] imagePos = msg.ImageInfo.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                int addPos = 0;//
                int currPos = 0;//当前正要添加的文本位置
                int textPos = 0;
                for (int i = 0; i < imagePos.Length; i++)
                {
                    string[] imageContent = imagePos[i].Split(',');//获得图片所在的位置、图片名称 
                    currPos = Convert.ToInt32(imageContent[0]);//获得图片所在的位置

                    if (i == 0)
                        txtRecord.AppendText(AddHeadSpace("\n" + msg.Content.Substring(textPos, currPos - addPos)));
                    else
                        txtRecord.AppendText(AddHeadSpace(msg.Content.Substring(textPos, currPos - addPos)));

                    txtRecord.SelectionStart = txtRecord.TextLength;

                    textPos += currPos - addPos + 1;
                    addPos += currPos - addPos;

                    Image image = null;
                    //if (IsSend)//如果图片是自己发送给自己的
                    //{
                    //    image = txtSend.GetPicture(imageContent[1]).Image;
                    //}
                    //else//如果图片是对方发送过来的
                    //{
                    if (txtRecord.GetPicture(imageContent[1]) != null)
                        image = txtRecord.GetPicture(imageContent[1]).Image;
                    else
                    {
                        string fileName = Path.Combine(EngineContext.Current.FilePathManager.ImagePath, imageContent[1] + ".gif");
                        if (System.IO.File.Exists(fileName)) //如果本地已经有此文件已经存在 
                            image = System.Drawing.Image.FromFile(fileName);
                    }

                    if (imageContent[1].Length < 32 && image == null)
                        image = System.Drawing.Image.FromFile(Application.StartupPath + @"\face\" + imageContent[1] + ".gif");
                    //}
                    if (image == null)
                    {
                        image = Properties.Resources.wite;
                        MyPicture pic = txtRecord.addGifControl(imageContent[1], image);
                        m_NeedRecPictures.Enqueue(pic);
                    }
                    else
                    {
                        txtRecord.addGifControl(imageContent[1], image);
                    }

                    addPos++;
                }
                string lastContent = AddHeadSpace(msg.Content.Substring(textPos, msg.Content.Length - textPos)) + "\n";

                this.txtRecord.AppendText(lastContent);
            }
            else //如果消息中没有图片，则直接添加消息文本
            {
                txtRecord.AppendText(AddHeadSpace("\n" + msg.Content) + "\n");
            }

            txtRecord.Select(iniPos, txtRecord.TextLength - iniPos);
            txtRecord.SelectionFont = msg.Font;
            txtRecord.SelectionColor = msg.Color;

            txtRecord.Select(txtRecord.TextLength, 0);
            txtRecord.ScrollToCaret();

            //激活下载图片线程
            if (m_NeedRecPictures.Count > 0)
            {
                m_AutoReset.Set();
            }
        }

        private string AddHeadSpace(string content)
        {
            return content.Replace("\n", "\n   ");
        }

        #endregion

        #region 下载本地没有的聊天记录内里的图片

        /// <summary>
        /// 初始化下载图片线程
        /// </summary>
        public void InitDownloadImgQueue()
        {
            m_NeedRecPictures = Queue.Synchronized(new Queue());
            m_DownImgThread = new Thread(new ThreadStart(() =>
            {
                while (m_HasItem)
                {
                    if (m_NeedRecPictures.Count > 0)
                    {
                        MyPicture pic = m_NeedRecPictures.Dequeue() as MyPicture;
                        if (pic != null)
                        {
                            string fullPath = Path.Combine(EngineContext.Current.FilePathManager.ImagePath, pic.MD5 + ".gif");
                            messageManage.m_ImageUpload.DownlodImage(pic.MD5, fullPath);
                            if (File.Exists(fullPath))
                            {
                                pic.Image = Image.FromFile(fullPath);
                            }
                            else
                            {
                                pic.Image = Resources.error;
                            }

                            this.Invalidate();
                        }
                    }
                    else
                    {
                        m_AutoReset.WaitOne();
                    }
                }
            }));
            m_DownImgThread.IsBackground = true;
            m_DownImgThread.Start();
        }

        #endregion

        #region 发送消息框事件处理过程

        private void txtSend_KeyDown(object sender, KeyEventArgs e)
        {
            //如果按下粘贴
            if (e.Control == true && e.KeyCode == Keys.V)
            {
                System.Windows.Forms.IDataObject data = Clipboard.GetDataObject();
                Image image = data.GetData(DataFormats.Bitmap) as Image;
                if (image != null)
                {
                    this.SaveAddImage(image);
                    e.Handled = true;
                }
                else
                {
                    DataFormats.Format FormatImage = DataFormats.GetFormat(DataFormats.Text);
                    string str = data.GetData(DataFormats.Text) as string;
                    if (!string.IsNullOrEmpty(str))
                    {
                        this.txtSend.Paste(FormatImage);
                        e.Handled = true;
                    }
                }
            }

            if (SendKeyDownHandler != null)
                SendKeyDownHandler(sender, e);
        }

        void txtSend_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.Text))
                e.Effect = DragDropEffects.All;
            else if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.All;
        }

        void txtSend_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] MyFiles;
                int i;
                // 将文件赋给一个数组。
                MyFiles = (string[])(e.Data.GetData(DataFormats.FileDrop));
                // 循环处理数组并将文件添加到列表中。
                List<string> needSend = new List<string>();
                for (i = 0; i <= MyFiles.Length - 1; i++)
                {
                    System.IO.FileInfo f = new System.IO.FileInfo(MyFiles[i]);
                    if (f.Exists)
                        needSend.Add(f.FullName);
                }

                if (SendFile != null)
                    SendFile(this, needSend);//触发发送文件事件
            }
            else if (e.Data.GetDataPresent(DataFormats.Text) && this.txtSend.SelectedText != "")
                e.Effect = DragDropEffects.Move;
            else if (e.Data.GetDataPresent(DataFormats.Text) && this.txtSend.SelectedText == "")
                e.Effect = DragDropEffects.Copy;
        }

        #endregion

        #region 获得发送的消息类
        /// <summary>
        /// 获得发送的消息类
        /// </summary>
        /// <returns></returns>
        private MessageContent GetSendMsg()
        {
            MessageContent msg = new MessageContent();
            //msg.Content = this.txtSend.Text.TrimEnd();//获得消息文本内容
            msg.Content = this.txtSend.Text;//获得消息文本内容
            msg.Font = this.txtSend.Font;
            msg.Color = this.txtSend.ForeColor;
            msg.ImageInfo = this.txtSend.GetImageInfo();
            return msg;
        }
        #endregion

        #region 双击留言区图片预览

        void txtRecord_MouseDoubleClick(object sender, MouseEventArgs e)
        {

        }

        #endregion
    }
}

